package com.tyut.filter;

import com.alibaba.cloud.commons.lang.StringUtils;
import com.alibaba.fastjson.JSONObject;
import com.tyut.entity.User;
import com.tyut.util.JwtUtil;
import com.tyut.vo.ResultJson;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.util.UriComponentsBuilder;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.List;

@Component
@ConfigurationProperties(prefix = "ignore.white")
public class GatewayFilter implements GlobalFilter, Ordered {

    List<String> urls;

    public List<String> getUrls() {
        return urls;
    }

    public void setUrls(List<String> urls) {
        this.urls = urls;
    }

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //获取request对象和response对象
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        //获取URI对象
        URI uri = request.getURI();
        //通过URI获取请求地址
        String path = uri.getPath();

        AntPathMatcher matcher = new AntPathMatcher();
        //循环判断白名单，如果请求地址在白名单中，则直接放行
        for (String url : urls) {
            if (matcher.match(url, path)) {
                return chain.filter(exchange);
            }
        }

        //获取请求头
        HttpHeaders headers = request.getHeaders();
        //获取请求头中的token
        List<String> tokens = headers.get("token");
        //如果请求头中没有token，表示缺少认证（未登录）
        if(tokens == null || tokens.isEmpty()){
            System.out.println(path);
            System.out.println(uri);
            return error(response, ResultJson.unlogin("缺少认证"));
        }

        String token = tokens.get(0);
        try {
            //校验token
            User user = JwtUtil.parse(token);
            //如果校验通过，则需要得到用户的id，并将其设置到controller中
            //让controller拿到用户的id，进而查询到用户信息
            //获取到uri后面的query
            String query = uri.getQuery();
            //拼接新的query
            StringBuilder newQuery = new StringBuilder();
            if(StringUtils.isNotBlank(query)){
                newQuery.append(query).append("&");
            }
            newQuery.append("sessionId=").append(user.getId());
            //uri中的query是只读的，所以需要重新构建一个URI
            URI newUri = UriComponentsBuilder.fromUri(uri).replaceQuery(newQuery.toString())
                    .build().toUri();
            //request中的URI是只读的，所以需要重新构建一个request
            ServerHttpRequest newRequest = request.mutate().uri(newUri).build();

            //exchange中的request是只读的，所以需要重新构建一个exchange
            //exchange也能通过exchange.mutate()重新构建
            ServerWebExchange newExchange = exchange.mutate().request(newRequest).build();

            //通过请求头中的token校验通过，则放行
            return chain.filter(newExchange);
        } catch (Exception e) {
            e.printStackTrace();
            return error(response, ResultJson.unlogin("非法请求"));
        }

    }
    private Mono<Void> error(ServerHttpResponse response , ResultJson resultJson){
        DataBuffer buffer = response.bufferFactory().wrap(JSONObject.toJSONString(resultJson).getBytes(StandardCharsets.UTF_8));
        return response.writeWith(Flux.just(buffer));
    }


    @Override
    public int getOrder() {
        return 0;
    }
}
